package com.xyht.medicine_management_system.modules.visit.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.xyht.medicine_management_system.common.commonReturn.CommonCodeEnum;
import com.xyht.medicine_management_system.common.commonReturn.CommonResult;
import com.xyht.medicine_management_system.common.commonReturn.ResponseResult;
import com.xyht.medicine_management_system.common.util.TimeUtil;
import com.xyht.medicine_management_system.modules.medicine.entity.MmsMedicine;
import com.xyht.medicine_management_system.modules.medicine.mapper.MmsMedicineMapper;
import com.xyht.medicine_management_system.modules.order.entity.MmsOrder;
import com.xyht.medicine_management_system.modules.order.entity.MmsOrderMedicineInfo;
import com.xyht.medicine_management_system.modules.order.entity.resp.OrderMedicineInfoResp;
import com.xyht.medicine_management_system.modules.order.mapper.MmsOrderMapper;
import com.xyht.medicine_management_system.modules.order.mapper.MmsOrderMedicineInfoMapper;
import com.xyht.medicine_management_system.modules.stock.entity.MmsMedicineStockLog;
import com.xyht.medicine_management_system.modules.stock.mapper.MmsMedicineStockLogMapper;
import com.xyht.medicine_management_system.modules.user.entity.MmsUser;
import com.xyht.medicine_management_system.modules.user.mapper.MmsUserMapper;
import com.xyht.medicine_management_system.modules.visit.entity.MmsMedicineVisit;
import com.xyht.medicine_management_system.modules.visit.entity.resp.*;
import com.xyht.medicine_management_system.modules.visit.mapper.MmsMedicineVisitMapper;
import com.xyht.medicine_management_system.modules.visit.service.MmsMedicineVisitService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;

import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

import static com.xyht.medicine_management_system.common.util.ParamCheckUtil.isNullOrEmpty;
import static com.xyht.medicine_management_system.modules.order.constant.OrderConstant.ORDER_STATUS_ORDER_CANCELLED;
import static com.xyht.medicine_management_system.modules.order.constant.OrderConstant.ORDER_STATUS_TO_BE_PAID;
import static com.xyht.medicine_management_system.modules.order.constant.OrderMedicineInfoConstant.ORDER_MEDICINE_INFO_REFUND;
import static com.xyht.medicine_management_system.modules.stock.constant.StockFlag.STOCK_SALE;
import static com.xyht.medicine_management_system.modules.visit.constant.DateTypeConstant.*;

/**
 * <p>
 * 访问表 服务实现类
 * </p>
 *
 * @author XYHT
 * @since 2023-12-17
 */
@Service
public class MmsMedicineVisitServiceImpl extends ServiceImpl<MmsMedicineVisitMapper, MmsMedicineVisit> implements MmsMedicineVisitService {

    @Resource
    private MmsMedicineVisitMapper medicineVisitMapper;
    @Resource
    private MmsUserMapper mmsUserMapper;
    @Resource
    private MmsMedicineMapper medicineMapper;
    @Resource
    private MmsOrderMapper mmsOrderMapper;
    @Resource
    private MmsOrderMedicineInfoMapper orderMedicineInfoMapper;
    @Resource
    private MmsUserMapper userMapper;
    @Resource
    private MmsMedicineStockLogMapper medicineStockLogMapper;

    @Override
    public ResponseResult getEachMedicineVisit(String classificationId, Integer dateType) {
        if (isNullOrEmpty(dateType)) {
            return CommonResult.failed(CommonCodeEnum.INVALID_PARAM);
        }
        List<MmsMedicineVisitDateAndCountResp> medicineVisitDateAndCountList = new ArrayList<>();


        switch (dateType) {
            //昨天
            case DATE_TYPE_YESTERDAY: {
                Date startDate = TimeUtil.GetStartDate(TimeUtil.AddDays(new Date(), -1));
                Date endDate = TimeUtil.AddMinute(startDate, 60);
                for (int i = 1; i < 25; i++) {
                    MmsMedicineVisitDateAndCountResp medicineVisitDateAndCountResp = new MmsMedicineVisitDateAndCountResp();

                    //分类
                    LambdaQueryWrapper<MmsMedicineVisit> medicineVisitLambdaQueryWrapper = new LambdaQueryWrapper<>();
                    getMedicineAndVisitIdByClassId(classificationId,medicineVisitLambdaQueryWrapper);

                    //日期
                    medicineVisitLambdaQueryWrapper
                            .ge(MmsMedicineVisit::getCreateTime,startDate)
                            .le(MmsMedicineVisit::getCreateTime,endDate);

                    Integer visitCount = medicineVisitMapper.selectCount(medicineVisitLambdaQueryWrapper);
                    medicineVisitDateAndCountResp.setVisitCount(visitCount);
                    medicineVisitDateAndCountResp.setVisitDate(String.valueOf(i));
                    startDate = TimeUtil.AddMinute(startDate, 60);
                    endDate = TimeUtil.AddMinute(endDate, 60);
                    medicineVisitDateAndCountList.add(medicineVisitDateAndCountResp);
                }
                break;
            }
            //上周
            case DATE_TYPE_LAST_WEEK: {
                Date lastWeek = TimeUtil.AddDays(new Date(), -7);
                Date startDateOfWeek = TimeUtil.GetStartDateOfWeek(lastWeek);
                Date endDateOfWeek = TimeUtil.GetEndDateOfWeek(lastWeek);
                while (startDateOfWeek.before(endDateOfWeek)){
                    MmsMedicineVisitDateAndCountResp medicineVisitDateAndCountResp = new MmsMedicineVisitDateAndCountResp();

                    startDateOfWeek = TimeUtil.AddDays(startDateOfWeek,1);

                    Date endDate = TimeUtil.GetEndDate(startDateOfWeek);
                    //分类
                    LambdaQueryWrapper<MmsMedicineVisit> medicineVisitLambdaQueryWrapper = new LambdaQueryWrapper<>();
                    getMedicineAndVisitIdByClassId(classificationId,medicineVisitLambdaQueryWrapper);

                    medicineVisitLambdaQueryWrapper
                            .ge(MmsMedicineVisit::getCreateTime,startDateOfWeek)
                            .le(MmsMedicineVisit::getCreateTime,endDate);

                    Integer visitCount = medicineVisitMapper.selectCount(medicineVisitLambdaQueryWrapper);
                    medicineVisitDateAndCountResp.setVisitCount(visitCount);
                    medicineVisitDateAndCountResp.setVisitDate(TimeUtil.getWeek(endDate));
                    medicineVisitDateAndCountList.add(medicineVisitDateAndCountResp);
                }
                break;
            }
            //上个月
            case DATE_TYPE_LAST_MONTH: {
                medicineVisitDateAndCountList = getLastYearVisit(classificationId);
                break;
            }
            //今年
            case DATE_TYPE_ONE_YEAR: {
                Date date = new Date();
                Calendar cal = Calendar.getInstance();
                //设置年份
                cal.setTime(date);
                //设置月份
                cal.set(Calendar.MONTH, 0);
                cal.set(Calendar.DATE,1);
                Date thisYearFistDate = cal.getTime();
                for (int i = 1; i < 13; i++) {
                     Date startDateOfMonth = TimeUtil.GetStartDateOfMonth(thisYearFistDate);
                    Date endDateOfMonth = TimeUtil.GetEndDateOfMonth(thisYearFistDate);
                    MmsMedicineVisitDateAndCountResp medicineVisitDateAndCountResp = new MmsMedicineVisitDateAndCountResp();

                    //分类
                    LambdaQueryWrapper<MmsMedicineVisit> medicineVisitLambdaQueryWrapper = new LambdaQueryWrapper<>();
                    getMedicineAndVisitIdByClassId(classificationId,medicineVisitLambdaQueryWrapper);

                    medicineVisitLambdaQueryWrapper
                            .ge(MmsMedicineVisit::getCreateTime,startDateOfMonth)
                            .le(MmsMedicineVisit::getCreateTime,endDateOfMonth);

                    Integer visitCount = medicineVisitMapper.selectCount(medicineVisitLambdaQueryWrapper);
                    medicineVisitDateAndCountResp.setVisitCount(visitCount);
                    medicineVisitDateAndCountResp.setVisitDate(TimeUtil.DateFormatSting(thisYearFistDate).substring(0,7));
                    medicineVisitDateAndCountList.add(medicineVisitDateAndCountResp);
                    thisYearFistDate = TimeUtil.AddMonths(thisYearFistDate,1);
                }
                break;
            }
        }

        return CommonResult.success(medicineVisitDateAndCountList);
    }

    @Override
    public ResponseResult getVisitData() {
        MmmVisitDataResp visitDataResp = new MmmVisitDataResp();

        //1.上个月访问量
        //这个月的第一天
        Date startMonth = TimeUtil.GetStartDateOfMonth(new Date());
        List<MmsMedicineVisitDateAndCountResp> lastYearVisit = getLastYearVisit(null);
        visitDataResp.setMedicineBeforeMonthVisitList(lastYearVisit);

        //2.用户数据
        MmsUserStatisticsResp mmsUserStatisticsResp = new MmsUserStatisticsResp();
        LambdaQueryWrapper<MmsUser> todayLambdaQueryWrapper = new LambdaQueryWrapper<>();
        LambdaQueryWrapper<MmsUser> yesLambdaQueryWrapper = new LambdaQueryWrapper<>();
        //今天的开始时间
        Date startDate = TimeUtil.GetStartDate(new Date());
        //今天的结束时间
        Date endDate = TimeUtil.GetEndDate(new Date());
        //今天的用户量
        todayLambdaQueryWrapper
                .ge(MmsUser::getCreateTime, startDate)
                .le(MmsUser::getCreateTime, endDate);
        //昨日的用户量
        yesLambdaQueryWrapper
                .ge(MmsUser::getCreateTime,TimeUtil.AddDays(startDate,-1))
                .le(MmsUser::getCreateTime,TimeUtil.AddDays(endDate,-1));
        Integer todayUserCount = mmsUserMapper.selectCount(todayLambdaQueryWrapper);
        Integer yesUserCount = mmsUserMapper.selectCount(yesLambdaQueryWrapper);

        int dayIncreaseCount = todayUserCount - yesUserCount;

        mmsUserStatisticsResp.setTodayUserCount(todayUserCount);
        mmsUserStatisticsResp.setDailyIncrementCount(dayIncreaseCount);
        visitDataResp.setUserStatisticsResp(mmsUserStatisticsResp);

        //3.当日访问量
        Integer nowCount = medicineVisitMapper.selectCount(new LambdaQueryWrapper<MmsMedicineVisit>()
                .ge(MmsMedicineVisit::getCreateTime, startDate)
                .le(MmsMedicineVisit::getCreateTime, endDate));
        visitDataResp.setNowVisitCount(nowCount);

        //4.本月的访问量
        List<MmsMedicineVisitDateAndCountResp> medicineThisMonthVisitList = new ArrayList<>();
        while (startMonth.before(endDate)){
            MmsMedicineVisitDateAndCountResp medicineThisMonthVisitResp = new MmsMedicineVisitDateAndCountResp();
            Date thisEndDate = TimeUtil.GetEndDate(startMonth);

            Integer count = medicineVisitMapper.selectCount(new LambdaQueryWrapper<MmsMedicineVisit>()
                    .ge(MmsMedicineVisit::getCreateTime, startMonth)
                    .le(MmsMedicineVisit::getCreateTime, thisEndDate));
            medicineThisMonthVisitResp.setVisitCount(count);
            medicineThisMonthVisitResp.setVisitDate(TimeUtil.DateFormatSting(startMonth));
            startMonth = TimeUtil.AddDays(startMonth,1);
            medicineThisMonthVisitList.add(medicineThisMonthVisitResp);
        }
        visitDataResp.setMedicineThisMonthVisitList(medicineThisMonthVisitList);

        //5.下单转化率
        //不是下单成功的状态
        List<Integer> orderStatus = new ArrayList<>();
        orderStatus.add(ORDER_STATUS_ORDER_CANCELLED);
        orderStatus.add(ORDER_STATUS_TO_BE_PAID);
        //总浏览量
        Integer sum = medicineVisitMapper.selectCount(new LambdaQueryWrapper<>());
        //下单量
        Integer orderCount = mmsOrderMapper.selectCount(new LambdaQueryWrapper<MmsOrder>()
                .notIn(MmsOrder::getOrderStatus, orderStatus));
        if (sum == 0) {
            visitDataResp.setOrderConversionRatio(0);
            visitDataResp.setNotOrderConversionRatio(0);
        }else {
            double orderConversionRatio = (double) orderCount / sum * 100;
            visitDataResp.setOrderConversionRatio((int)orderConversionRatio);
            int notOrderConversionRatio = 100 - orderCount;
            visitDataResp.setNotOrderConversionRatio(notOrderConversionRatio);
        }

        //6.计算各商品总访问量
        List<MmsMedicineVisitResp> medicineVisitList = getMedicineVisit();
        visitDataResp.setMedicineVisitList(medicineVisitList);

        return CommonResult.success(visitDataResp);
    }

    @Override
    public ResponseResult getMedicineVisitRanking() {
        List<MmsMedicineVisitRationResp> medicineVisitRationList = new ArrayList<>();

        Integer sum = medicineVisitMapper.selectCount(new LambdaQueryWrapper<>());
        List<MmsMedicineVisitResp> medicineVisit = getMedicineVisit();
        if (medicineVisit.isEmpty()) {
            return CommonResult.success(medicineVisitRationList);
        }

        int index = 0;
        int ration = 0;
        for (MmsMedicineVisitResp medicineVisitResp : medicineVisit) {
            MmsMedicineVisitRationResp medicineVisitRationResp = new MmsMedicineVisitRationResp();

            if (sum == 0) {
                medicineVisitRationResp.setMedicineVisitRation(0);
            } else {
                if (index == medicineVisit.size() - 1) {
                    medicineVisitRationResp.setMedicineVisitRation(100 - ration);
                } else {
                    double medicineRation = (double) medicineVisitResp.getMedicineVisitCount() / sum * 100;
                    medicineVisitRationResp.setMedicineVisitRation((int) medicineRation);
                    ration += medicineRation;
                }
            }
            //药品名
            medicineVisitRationResp.setMedicineName(medicineVisitResp.getMedicineName());
            medicineVisitRationList.add(medicineVisitRationResp);
            index++;
        }
        medicineVisitRationList.sort((o2, o1) -> o1.getMedicineVisitRation().compareTo(o2.getMedicineVisitRation()));
        return CommonResult.success(medicineVisitRationList);
    }

    @Override
    public ResponseResult getSalesStatistics(Integer dateType ,Integer lastNumber) {
        if (isNullOrEmpty(dateType)) {
            return CommonResult.failed(CommonCodeEnum.INVALID_PARAM);
        }
        List<MmmOrderDateAndAmountResp> orderDateAndAmountList = new ArrayList<>();

        switch (dateType){
            //每周
            case DATE_TYPE_EVERY_WEEK :{
                Calendar calendar = Calendar.getInstance();
                calendar.setTime(new Date());

                // 判断今天是否是星期日
                boolean isSunday = calendar.get(Calendar.DAY_OF_WEEK) == Calendar.SUNDAY;
                if (isSunday) {
                    lastNumber = lastNumber +1;
                }
                Date lastWeek = TimeUtil.AddDays(new Date(), -7 * lastNumber);
                Date startDateOfWeek = TimeUtil.GetStartDateOfWeek(lastWeek);
                Date endDateOfWeek = TimeUtil.GetEndDateOfWeek(lastWeek);
                while (startDateOfWeek.before(endDateOfWeek)) {

                    //周几的0点加一天
                    startDateOfWeek = TimeUtil.AddDays(startDateOfWeek, 1);
                    //周几的23:99:99
                    Date endDate = TimeUtil.GetEndDate(startDateOfWeek);
                    //构造条件查询销售额
                    BigDecimal salesAmount = getSalesAmount(startDateOfWeek, endDate);

                    MmmOrderDateAndAmountResp orderDateAndAmountResp = new MmmOrderDateAndAmountResp();
                    orderDateAndAmountResp.setDate(TimeUtil.getWeek(endDate));
                    orderDateAndAmountResp.setSalesAmount(salesAmount);
                    orderDateAndAmountList.add(orderDateAndAmountResp);
                }
                break;
            }
            //每月
            case DATE_TYPE_EVERY_MONTH  :{

                //这个月的第一天
                Date startMonth = TimeUtil.GetStartDateOfMonth(new Date());
                //上个月的第一天
                Date beforeStartMonth = TimeUtil.AddMonths(startMonth, -1 * lastNumber);
                //上月的最后一天
                Date endDateOfMonth = TimeUtil.GetEndDateOfMonth(beforeStartMonth);
                while (beforeStartMonth.before(endDateOfMonth)) {

                    //beforeStartMonth当天的最后时间
                    Date endDate = TimeUtil.GetEndDate(beforeStartMonth);
                    //构造条件查询销售额
                    BigDecimal salesAmount = getSalesAmount(beforeStartMonth, endDate);

                    beforeStartMonth = TimeUtil.AddDays(beforeStartMonth, 1);

                    MmmOrderDateAndAmountResp orderDateAndAmountResp = new MmmOrderDateAndAmountResp();
                    orderDateAndAmountResp.setSalesAmount(salesAmount);
                    orderDateAndAmountResp.setDate(TimeUtil.DateFormatSting(endDate).substring(8,10));
                    orderDateAndAmountList.add(orderDateAndAmountResp);
                }
                break;
            }
            //每季度
            case DATE_TYPE_EVERY_QUARTER :{

                // 使用Calendar对象来处理日期
                Calendar calendar = Calendar.getInstance();
                calendar.setTime(new Date());
                // 获取当前月份
                int currentMonth = calendar.get(Calendar.MONTH) + 1;
                // 计算当前季度
                int currentQuarter = (currentMonth + 2) / 3; // 因为季度是从0开始计数的

                // 设置季度开始月份（季度开始月份是该季度的第一个月）
                calendar.set(Calendar.MONTH, currentQuarter * 3 - 3); // -2是因为月份是从0开始的，所以要减去2才能得到正确的季度开始月份
                Date quarterStartDate = TimeUtil.GetStartDateOfMonth(calendar.getTime());
                quarterStartDate = TimeUtil.AddMonths(quarterStartDate,-3 * lastNumber);
                // 设置季度结束月份（季度结束月份是该季度的最后一个月）
                calendar.set(Calendar.MONTH, currentQuarter * 3 -1);
                Date quarterEndDate = TimeUtil.GetEndDateOfMonth(calendar.getTime());
                quarterEndDate = TimeUtil.AddMonths(quarterEndDate,-3 * lastNumber);
                while (quarterStartDate.before(quarterEndDate)){

                    //quarterStartDate的月底时间
                    Date monthEndDate = TimeUtil.GetEndDateOfMonth(quarterStartDate);
                    BigDecimal salesAmount = getSalesAmount(quarterStartDate, monthEndDate);

                    quarterStartDate = TimeUtil.AddMonths(quarterStartDate,1);

                    MmmOrderDateAndAmountResp orderDateAndAmountResp = new MmmOrderDateAndAmountResp();
                    orderDateAndAmountResp.setSalesAmount(salesAmount);
                    orderDateAndAmountResp.setDate(TimeUtil.DateFormatSting(monthEndDate).substring(5,7));
                    orderDateAndAmountList.add(orderDateAndAmountResp);


                }

                break;
            }
            //每年
            case DATE_TYPE_EVERY_YEAR :{

                // 设置年份
                Calendar calendar = Calendar.getInstance();
                calendar.setTime(new Date());
                int year = calendar.get(Calendar.YEAR);
                calendar.set(Calendar.YEAR, year - lastNumber);
                //设置月份
                calendar.set(Calendar.MONTH, 0);
                calendar.set(Calendar.DATE, 1);
                Date thisYearFistDate = calendar.getTime();
                for (int i = 1; i < 13; i++) {
                    Date startDateOfMonth = TimeUtil.GetStartDateOfMonth(thisYearFistDate);
                    Date endDateOfMonth = TimeUtil.GetEndDateOfMonth(thisYearFistDate);

                    //构造条件查询销售额
                    BigDecimal salesAmount = getSalesAmount(startDateOfMonth, endDateOfMonth);
                    thisYearFistDate = TimeUtil.AddMonths(thisYearFistDate, 1);

                    MmmOrderDateAndAmountResp orderDateAndAmountResp = new MmmOrderDateAndAmountResp();
                    orderDateAndAmountResp.setSalesAmount(salesAmount);
                    orderDateAndAmountResp.setDate(TimeUtil.DateFormatSting(startDateOfMonth).substring(0, 7));
                    orderDateAndAmountList.add(orderDateAndAmountResp);

                }
                break;
            }
        }

        return CommonResult.success(orderDateAndAmountList);
    }

    @Override
    public ResponseResult getCustomerPurchaseStatistics(Integer pageNum,Integer pageSize) {

        List<MmsCustomerPurchaseStatisticsResp> customerPurchaseStatisticsList = new ArrayList<>();
        Page<MmsOrder> page = new Page<>(pageNum,pageSize);
        mmsOrderMapper.selectPage(page,new LambdaQueryWrapper<MmsOrder>()
                .isNotNull(MmsOrder::getPaymentAmount)
                .orderByDesc(MmsOrder::getPaymentTime));
        List<MmsOrder> orderList = page.getRecords();
        int total = (int)page.getTotal();
        if (orderList == null || orderList.size() < 1) {
            return CommonResult.success(customerPurchaseStatisticsList,total);
        }
        for (MmsOrder order : orderList) {

            String customerId = order.getUserId();
            MmsUser mmsUser = userMapper.selectById(customerId);

            String medicineInfo = order.getMedicineInfo();
            List<OrderMedicineInfoResp> orderMedicineInfoList = JSONObject.parseArray(medicineInfo, OrderMedicineInfoResp.class);
            if (orderMedicineInfoList.isEmpty()) {
                return CommonResult.success(customerPurchaseStatisticsList);
            }
            for (OrderMedicineInfoResp orderMedicineInfoResp : orderMedicineInfoList) {
                MmsCustomerPurchaseStatisticsResp medicineSaleStatisticsResp = new MmsCustomerPurchaseStatisticsResp();
                MmsMedicine medicine = orderMedicineInfoResp.getMedicine();
                if (!isNullOrEmpty(medicine)) {
                    medicineSaleStatisticsResp.setSaleAmount(orderMedicineInfoResp.getMedicineNum());
                    medicineSaleStatisticsResp.setSaleDate(order.getPaymentTime());
                    MmsUserStatisticInfoResp mmsUserStatisticInfoResp = new MmsUserStatisticInfoResp();
                    if (!isNullOrEmpty(mmsUser)) {
                        BeanUtils.copyProperties(mmsUser, mmsUserStatisticInfoResp);
                    }
                    medicineSaleStatisticsResp.setUserInfo(mmsUserStatisticInfoResp);
                    medicineSaleStatisticsResp.setMedicineName(medicine.getCommonNames());
                }
                customerPurchaseStatisticsList.add(medicineSaleStatisticsResp);
            }
        }
        return CommonResult.success(customerPurchaseStatisticsList,total);
    }

    @Override
    public ResponseResult getReturnStatistics(Integer pageNum,Integer pageSize,Integer dateType) {
        if (isNullOrEmpty(dateType)) {
            return CommonResult.failed(CommonCodeEnum.INVALID_PARAM);
        }
        List<MmsMedicineRefundResp> medicineRefundList = new ArrayList<>();
        Page<Map<String, Object>> page = new Page<>(pageNum,pageSize);
        switch (dateType) {
            case DATE_TYPE_YESTERDAY: {
                Date startDate = TimeUtil.GetStartDate(TimeUtil.AddDays(new Date(), -1));
                Date endDate = TimeUtil.GetEndDate(startDate);
                medicineRefundList = getMedicineRefundList(page,startDate, endDate);
                break;
            }

            case DATE_TYPE_LAST_WEEK: {
                Date lastWeek = TimeUtil.AddDays(new Date(), -7);
                Date startDateOfWeek = TimeUtil.GetStartDateOfWeek(lastWeek);
                Date endDateOfWeek = TimeUtil.GetEndDateOfWeek(lastWeek);
                medicineRefundList = getMedicineRefundList(page,startDateOfWeek, endDateOfWeek);
                break;
            }

            case DATE_TYPE_LAST_MONTH: {
                //这个月的第一天
                Date startMonth = TimeUtil.GetStartDateOfMonth(new Date());
                //上个月的第一天
                Date beforeStartMonth = TimeUtil.AddMonths(startMonth, -1);
                //上月的最后一天
                Date endDateOfMonth = TimeUtil.GetEndDateOfMonth(beforeStartMonth);
                medicineRefundList = getMedicineRefundList(page,beforeStartMonth, endDateOfMonth);
                break;
            }

            case DATE_TYPE_ONE_YEAR: {
                Date date = new Date();
                Calendar cal = Calendar.getInstance();
                //设置年份
                cal.setTime(date);
                //设置月份
                cal.set(Calendar.MONTH, 0);
                cal.set(Calendar.DATE, 1);
                cal.set(Calendar.DAY_OF_MONTH, 1);
                cal.set(Calendar.HOUR, 0);
                cal.set(Calendar.HOUR_OF_DAY, 0);
                cal.set(Calendar.MINUTE, 0);
                cal.set(Calendar.SECOND, 0);
                cal.set(Calendar.MILLISECOND, 0);
                Date thisYearFistDate = cal.getTime();
                Date thisYearEndDate = TimeUtil.GetEndDateOfMonth(TimeUtil.AddMonths(thisYearFistDate,11));
                medicineRefundList = getMedicineRefundList(page,thisYearFistDate, thisYearEndDate);
                break;
            }

        }
        int total = (int)page.getTotal();
        return CommonResult.success(medicineRefundList,total);
    }

    @Override
    public ResponseResult getMedicineRanking() {

        List<MmsMedicineSaleRankingResp> medicineSaleRankingList = new ArrayList<>();

        List<Map<String, Object>> maps = medicineStockLogMapper.selectMaps(new QueryWrapper<MmsMedicineStockLog>()
                .select("medicine_code as medicineName,count(*) as saleAmount")
                .lambda()
                .eq(MmsMedicineStockLog::getStockFlag, STOCK_SALE)
                .groupBy(MmsMedicineStockLog::getMedicineCode));
        if (maps.isEmpty()) {
            return CommonResult.success(medicineSaleRankingList);
        }
        for (Map<String, Object> map : maps) {
            MmsMedicineSaleRankingResp medicineSaleRankingResp = JSONObject.parseObject(JSON.toJSONString(map), MmsMedicineSaleRankingResp.class);
            if (!isNullOrEmpty(medicineSaleRankingResp)) {
                MmsMedicineSaleRankingResp medicineSaleRanking = new MmsMedicineSaleRankingResp();
                List<MmsMedicineStockLog> medicineStockLogList = medicineStockLogMapper.selectList(new LambdaQueryWrapper<MmsMedicineStockLog>()
                        .eq(MmsMedicineStockLog::getMedicineCode, medicineSaleRankingResp.getMedicineName()));
                if (!medicineStockLogList.isEmpty()) {
                    medicineSaleRanking.setMedicineName(medicineStockLogList.get(0).getMedicineName());
                    medicineSaleRanking.setSaleAmount(medicineSaleRankingResp.getSaleAmount());
                    medicineSaleRankingList.add(medicineSaleRanking);
                }
            }
        }
        if (!medicineSaleRankingList.isEmpty()) {
            medicineSaleRankingList.sort((o2, o1) -> o1.getSaleAmount().compareTo(o2.getSaleAmount()));
        }
        return CommonResult.success(medicineSaleRankingList);
    }

    @Override
    public ResponseResult getMedicineSaleStatistics() {
        List<MmsMedicineSaleStatisticsResp> medicineSaleStatisticsList = new ArrayList<>();
        List<MmsMedicine> medicineList = medicineMapper.selectList(new LambdaQueryWrapper<>());
        if (medicineList.isEmpty()) {
            return CommonResult.success(medicineSaleStatisticsList);
        }
        for (MmsMedicine medicine : medicineList) {
            MmsMedicineSaleStatisticsResp medicineSaleStatisticsResp = new MmsMedicineSaleStatisticsResp();
            int saleAmount = 0;
            List<MmsMedicineStockLog> medicineStockLogList = medicineStockLogMapper.selectList(new LambdaQueryWrapper<MmsMedicineStockLog>()
                    .eq(MmsMedicineStockLog::getMedicineCode, medicine.getMedicineCode())
                    .eq(MmsMedicineStockLog::getStockFlag, STOCK_SALE));
            for (MmsMedicineStockLog mmsMedicineStockLog : medicineStockLogList) {
                saleAmount += mmsMedicineStockLog.getOutQuantity();
            }
            medicineSaleStatisticsResp.setSaleAmount(saleAmount);
            medicineSaleStatisticsResp.setMedicineName(medicine.getCommonNames());
            medicineSaleStatisticsList.add(medicineSaleStatisticsResp);
        }
        if (!medicineSaleStatisticsList.isEmpty()) {
            medicineSaleStatisticsList.sort((o2, o1) -> o1.getSaleAmount().compareTo(o2.getSaleAmount()));
        }
        return CommonResult.success(medicineSaleStatisticsList);
    }

    /**
     *
     * @param startDate 开始时间
     * @param endDate 结束时间
     * @return 销售额
     */
    private BigDecimal getSalesAmount(Date startDate,Date endDate){
        List<MmsOrder> orderList = mmsOrderMapper.selectList(new LambdaQueryWrapper<MmsOrder>()
                .isNotNull(MmsOrder::getPaymentAmount)
                .ge(MmsOrder::getPaymentTime, startDate)
                .le(MmsOrder::getPaymentTime, endDate));

        BigDecimal salesAmount = new BigDecimal(0);
        if (!orderList.isEmpty()){
            for (MmsOrder mmsOrder : orderList) {
                salesAmount = salesAmount.add(mmsOrder.getPaymentAmount());
            }
        }
        return salesAmount;
    }

    /**
     *
     * @return 计算各商品总访问量
     */
    private List<MmsMedicineVisitResp> getMedicineVisit(){
        List<MmsMedicineVisitResp> medicineVisitList = new ArrayList<>();
        QueryWrapper<MmsMedicineVisit> medicineVisitLambdaQueryWrapper = new QueryWrapper<>();
        medicineVisitLambdaQueryWrapper.select("count(*) as medicineVisitCount,visit_id as medicineName")
                .lambda()
                .groupBy(MmsMedicineVisit::getVisitId);
        List<Map<String, Object>> maps = medicineVisitMapper.selectMaps(medicineVisitLambdaQueryWrapper);
        if (maps.isEmpty()) {
            return medicineVisitList;
        }

        for (Map<String, Object> map : maps) {
            MmsMedicineVisitResp medicineVisitResp = new MmsMedicineVisitResp();
            MmsMedicineVisitResp mmsMedicineVisitResp = JSONObject.parseObject(JSON.toJSONString(map), MmsMedicineVisitResp.class);
            if (!isNullOrEmpty(mmsMedicineVisitResp)) {
                //药品名
                String medicineId = mmsMedicineVisitResp.getMedicineName();
                MmsMedicine medicine = medicineMapper.selectById(medicineId);
                if (!isNullOrEmpty(medicine)) {
                    medicineVisitResp.setMedicineName(medicine.getCommonNames());
                    medicineVisitResp.setMedicineVisitCount(mmsMedicineVisitResp.getMedicineVisitCount());
                    medicineVisitList.add(medicineVisitResp);
                }
            }

        }
        if (!medicineVisitList.isEmpty()) {
            medicineVisitList.sort((o2, o1) -> o1.getMedicineVisitCount().compareTo(o2.getMedicineVisitCount()));
        }
        return medicineVisitList;
    }


    /**
     *
     * @return 上个月访问日期和访问量
     */
    private List<MmsMedicineVisitDateAndCountResp> getLastYearVisit(String classificationId){
        //1.上个月访问量
        List<MmsMedicineVisitDateAndCountResp> medicineMonthVisitList = new ArrayList<>();
        //这个月的第一天
        Date startMonth = TimeUtil.GetStartDateOfMonth(new Date());
        //上个月的第一天
        Date beforeStartMonth = TimeUtil.AddMonths(startMonth, -1);
        //上月的最后一天
        Date endDateOfMonth = TimeUtil.GetEndDateOfMonth(beforeStartMonth);
        while (beforeStartMonth.before(endDateOfMonth)){
            MmsMedicineVisitDateAndCountResp medicineMonthVisitResp = new MmsMedicineVisitDateAndCountResp();

            //分类
            LambdaQueryWrapper<MmsMedicineVisit> medicineVisitLambdaQueryWrapper = new LambdaQueryWrapper<>();
            if (!isNullOrEmpty(classificationId)) {
                getMedicineAndVisitIdByClassId(classificationId,medicineVisitLambdaQueryWrapper);
            }
            Date endDate = TimeUtil.GetEndDate(beforeStartMonth);

            Integer count = medicineVisitMapper.selectCount(new LambdaQueryWrapper<MmsMedicineVisit>()
                    .ge(MmsMedicineVisit::getCreateTime, beforeStartMonth)
                    .le(MmsMedicineVisit::getCreateTime, endDate));
            medicineMonthVisitResp.setVisitCount(count);
            medicineMonthVisitResp.setVisitDate(TimeUtil.DateFormatSting(endDate));
            beforeStartMonth = TimeUtil.AddDays(beforeStartMonth,1);
            medicineMonthVisitList.add(medicineMonthVisitResp);
        }
        return medicineMonthVisitList;
    }

    /**
     *
     * @param classificationId 分类id
     * @param medicineVisitLambdaQueryWrapper 构造器
     */
    private void getMedicineAndVisitIdByClassId(String classificationId,LambdaQueryWrapper<MmsMedicineVisit> medicineVisitLambdaQueryWrapper){
        if (!isNullOrEmpty(classificationId)) {
            List<MmsMedicine> medicineList = medicineMapper.selectList(new LambdaQueryWrapper<MmsMedicine>()
                    .eq(MmsMedicine::getClassificationId, classificationId));
            if (!medicineList.isEmpty()) {
                List<String> medicineIdList = medicineList.stream().map(MmsMedicine::getId).collect(Collectors.toList());
                medicineVisitLambdaQueryWrapper.in(MmsMedicineVisit::getVisitId, medicineIdList);
            }else {
                medicineVisitLambdaQueryWrapper.in(MmsMedicineVisit::getVisitId, "");
            }
        }
    }

    /**
     *
     * @param page 分页
     * @param startDate 开始时间
     * @param endDate 结果时间
     * @return 退货信息
     */
    private List<MmsMedicineRefundResp> getMedicineRefundList(Page<Map<String, Object>> page,Date startDate,Date endDate){

        List<MmsMedicineRefundResp> medicineRefundList = new ArrayList<>();
        orderMedicineInfoMapper.selectMapsPage(page, new QueryWrapper<MmsOrderMedicineInfo>()
                .select("medicine_code as medicineName,sum(num) as saleAmount")
                .lambda()
                .isNotNull(MmsOrderMedicineInfo::getRefundId)
                .eq(MmsOrderMedicineInfo::getType, ORDER_MEDICINE_INFO_REFUND)
                .ge(MmsOrderMedicineInfo::getUpdateTime, startDate)
                .le(MmsOrderMedicineInfo::getUpdateTime, endDate)
                .groupBy(MmsOrderMedicineInfo::getMedicineCode));
        List<Map<String, Object>> mapList = page.getRecords();
        if (mapList.isEmpty()) {
            return medicineRefundList;
        }
        for (Map<String, Object> map : mapList) {
            MmsMedicineRefundResp medicineRefundRe = JSONObject.parseObject(JSON.toJSONString(map), MmsMedicineRefundResp.class);
            if (isNullOrEmpty(medicineRefundRe)) {
                continue;
            }
            List<MmsOrderMedicineInfo> medicineInfoList = orderMedicineInfoMapper.selectList(new LambdaQueryWrapper<MmsOrderMedicineInfo>()
                    .eq(MmsOrderMedicineInfo::getMedicineCode, medicineRefundRe.getMedicineName()));
            if (medicineInfoList.isEmpty()) {
                continue;
            }
            MmsMedicine medicine = JSONObject.parseObject(medicineInfoList.get(0).getMedicineInfo(), MmsMedicine.class);
            if (isNullOrEmpty(medicine)) {
                continue;
            }
            MmsMedicineRefundResp mmsMedicineRefundResp = new MmsMedicineRefundResp();
            mmsMedicineRefundResp.setMedicineName(medicine.getCommonNames());
            mmsMedicineRefundResp.setSaleAmount(medicineRefundRe.getSaleAmount());
            medicineRefundList.add(mmsMedicineRefundResp);
        }

        if (!medicineRefundList.isEmpty()) {
            medicineRefundList.sort((o2, o1) -> o1.getSaleAmount().compareTo(o2.getSaleAmount()));
        }
        return medicineRefundList;
    }
}
